﻿namespace MsForgeReboot.Tests.Areas.ControlPanel.Controllers {
    #region Usings

    using System.Collections.Generic;
    using System.Security.Principal;
    using System.Web;
    using System.Web.Mvc;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Moq;
    using MsForgeReboot.Framework.Entities;
    using MsForgeReboot.Framework.Interfaces;
    using MsForgeReboot.Framework.ViewModels;
    using MsForgeReboot.Web;
    using MsForgeReboot.Web.Areas.ControlPanel.Controllers;
    using PagedList;

    #endregion

    [TestClass]
    public class EventControllerTests {
        private Mock<IEventService> eventService;

        private Mock<IUserService> userService;

        private EventController controller;

        [TestInitialize]
        public void TestInitialize() {
            
            AutomapperConfig.Configure();
            
            this.eventService = new Mock<IEventService>();
            this.userService = new Mock<IUserService>();
            this.controller = new EventController(this.eventService.Object, this.userService.Object);
        }

        public void TestCleanup() {
            this.eventService = null;
        }

        [TestMethod]
        public void InstantiateEventController() {
            Assert.IsNotNull(controller);
        }

        [TestMethod]
        public void GetUpcomingEventsReturnsListOfEvents() {
            this.eventService.Setup(service => service.UpcomingEvents(1, 10))
                .Returns(new List<Event>().ToPagedList(1, 10));

            var result = this.controller.Index(1, 10) as ViewResult;

            Assert.IsInstanceOfType(result.Model, typeof(IPagedList<Event>));

            this.eventService.Verify();
        }

        [TestMethod]
        public void CreateNewEventForm() {

            var controllerContext = new Mock<ControllerContext>();
            controllerContext.SetupGet(cc => cc.HttpContext.User.Identity.Name).Returns("test@user.com");
            
            this.userService.Setup(us => us.GetSingleUser(It.IsAny<string>())).Returns(new User() { Id = 123 });

            controller.ControllerContext = controllerContext.Object;

            var result = this.controller.Create() as ViewResult;

            Assert.IsInstanceOfType(result.Model, typeof(EventEditModel));
            Assert.AreEqual("Edit", result.ViewName);

            this.eventService.Verify();
        }

        [TestMethod]
        public void SaveNewEvent() {
          
            var model = new EventEditModel {
                                      Id = 0,
                                      Title = "Test Event",
                                      Body = "The quick brown fox jumps over the lazy dog",
                                      Author = new UserViewModel { Id = 1 }
                                  };

            var result = (RedirectToRouteResult)this.controller.Edit(model);
            Assert.AreEqual("Index", result.RouteValues["action"]);
            this.eventService.Verify(service => service.Save(It.IsAny<Event>()), Times.Exactly(1));
        }

        [TestMethod]
        public void SaveNewEventRedirectToEditIfModelStateIsInvalid() {
            this.controller.ModelState.AddModelError(
                "", "fake error message, simulation of defaultModelBinder behaviour");

            var model = new EventEditModel {
                Id = 0,
                Title = "Test Event",
                Body = "The quick brown fox jumps over the lazy dog",
                Author = new UserViewModel { Id = 1 }
            };

            var result = this.controller.Edit(model) as ViewResult;

            Assert.AreEqual("Edit", result.ViewName);
            this.eventService.Verify(service => service.Save(It.IsAny<Event>()), Times.Never);
        }

        [TestMethod]
        public void DeleteUserGroupByUrlPointer() {
            this.eventService.Setup(service => service.Delete("Title-1"));

            var result = this.controller.Delete("Title-1") as JsonResult;

            Assert.AreEqual(result.Data, "success");
            Assert.AreEqual(result.JsonRequestBehavior, JsonRequestBehavior.DenyGet);

            this.eventService.VerifyAll();
        }

        [TestMethod]
        public void EditUserGroupByUrlPointer() {
            this.eventService.Setup(service => service.GetByUrlPointer("Title-1"))
                .Returns(
                    new Event {
                                  Id = 20,
                                  Title = "Title 20",
                                  Body = "Body 20",
                                  Author = new User { Id = 5, PublicName = "test public name 5" }
                              });

            var result = this.controller.Edit("Title-1") as ViewResult;
            var model = result.Model as EventEditModel;

            Assert.AreEqual(model.Id, 20);
            Assert.AreEqual(model.Title, "Title 20");
            Assert.AreEqual(model.Body, "Body 20");
            Assert.AreEqual(model.Author.Id, 5);

            this.eventService.VerifyAll();
        }
    }
}
